#include "ItemModel.h"
#include "ItemGroup.h"
#include "Item.h"
#include "Defines.h"


ItemModel::ItemModel(QObject* parent)
    : QAbstractItemModel(parent)
{
}



ItemModel::ItemModel(ItemGroup *root, QObject *parent)
    : QAbstractItemModel(parent)
{
    m_root = root;
}



ItemModel::~ItemModel()
{
    if (!m_root.isNull() && !m_root->parent()) m_root->deleteLater();
}



QModelIndex ItemModel::index(int row, int column, const QModelIndex &parent) const
{
    if (m_root.isNull() || !hasIndex(row, column, parent)) return QModelIndex();

    AbstractItem* parentItem = 0;
    if (!parent.isValid())
    {
        parentItem = m_root.data();
    }
    else
    {
        parentItem = static_cast<AbstractItem*>(parent.internalPointer());
    }

    if (!parentItem || parentItem->itemCount() <= row)
    {
        return QModelIndex();
    }


    AbstractItem* item = parentItem->itemAt(row);
    if (!item) return QModelIndex();

    return createIndex(row, column, item);
}



QModelIndex ItemModel::parent(const QModelIndex &child) const
{
    if (m_root.isNull() || !child.isValid()) return QModelIndex();

    AbstractItem* childItem = static_cast<AbstractItem*>(child.internalPointer());
    if (!childItem) return QModelIndex();

    AbstractItem* item = qobject_cast<AbstractItem*>(childItem->parent());
    if (!item || item == m_root.data()) return QModelIndex();

    int row = item->children().indexOf(childItem);
    return createIndex(row, 0, item);
}



int ItemModel::rowCount(const QModelIndex &parent) const
{
    if (m_root.isNull()) return 0;

    ItemGroup* group = 0;
    if (!parent.isValid())  group = m_root.data();
    else                    group = static_cast<ItemGroup*>(parent.internalPointer());

    if (!group) return 0;

    return group->itemCount();
}



int ItemModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_root->fieldCount();
}



QVariant ItemModel::data(const QModelIndex &index, int role) const
{
    if (m_root.isNull() || !index.isValid() || role != Qt::DisplayRole) return QVariant();

    AbstractItem* item = static_cast<AbstractItem*>(index.internalPointer());
    if (!item) return QVariant();

    return item->data(index.column());
}



bool ItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid() || role != Qt::EditRole) return false;

    AbstractItem* item = static_cast<AbstractItem*>(index.internalPointer());
    if (!item) return false;

    int data_type = index.column();
    item->setData(data_type, value);
    return true;
}



QVariant ItemModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    Q_UNUSED(orientation);

    if (role != Qt::DisplayRole) return QVariant();

    if (section < 0 || section >= m_root->fieldCount()) return QVariant();

    // todo: all data type names to common defines.
    switch (section)
    {
    case AbstractItem::TypeData: return tr("Type");
    case AbstractItem::NameData: return tr("Name");
    case AbstractItem::DescData: return tr("Description");

    case Item::ValueData: return tr("Value");
    default: return tr("Unknown Field");
    }
}



